package com.wallet.my.service.impl;

import com.wallet.my.dao.mapper.AccountMapper;
import com.wallet.my.dao.mapper.TransRecordMapper;
import com.wallet.my.dao.pojo.TransRecordDO;
import com.wallet.my.service.ListenerService;
import com.wallet.my.util.EthUtil;
import io.reactivex.disposables.Disposable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.DefaultBlockParameterNumber;
import org.web3j.utils.Convert;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;

/**
 * 监听地址交易的接口实现类
 **/
@Service
public class ListenerServiceImpl implements ListenerService {
    @Autowired
    private Web3j web3j;
    @Autowired
    private TransRecordMapper transRecordMapper;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private TransRecordDO transRecordDO;
    @Autowired
    private EthUtil ethUtil;

//    查询指定区块区间的所有交易，from和to如果和自己的address相同，则把交易信息存到transRecord表
@Override
@Async                //耗时比较长，所以开启异步调用
public void addTransRecord(Long startBlockNum, Long endBlockNum, List<String> addrList) {
    DefaultBlockParameter startBlock = new DefaultBlockParameterNumber(startBlockNum);
    DefaultBlockParameter endBlock = new DefaultBlockParameterNumber(endBlockNum);

    Disposable subscribe = web3j.replayPastTransactionsFlowable(startBlock, endBlock).subscribe(transaction -> {
        String fromAddr = transaction.getFrom();
        String toAddr = transaction.getTo();
        for (String addr:addrList){
            if (addr.equals(fromAddr)||addr.equals(toAddr)){          //如果两个地址都在库里，这里每次会重复存入两笔交易记录，共4笔insert … select … where not exist ……
                String uuid = ethUtil.getUUID();
                String hash = transaction.getHash();
                String nonce=transaction.getNonce().toString();
                String blockNumber = transaction.getBlockNumber().toString();
                String transValue = Convert.fromWei(transaction.getValue().toString(), Convert.Unit.ETHER).toString();
                transRecordDO.setId(uuid);
                transRecordDO.setHash(hash);
                transRecordDO.setNonce(nonce);
                transRecordDO.setBlockNumber(blockNumber);
                transRecordDO.setFromAddr(fromAddr);
                transRecordDO.setToAddr(toAddr);
                transRecordDO.setTransValue(transValue);
                transRecordMapper.addTransRecord(transRecordDO);
            }
        }
    });
}

    //开始监听新增区块的交易，并和address比较
    @Override
    @Async
    public void listenTransRecord(List<String> addrList){
        Disposable subscribe = web3j.transactionFlowable().subscribe(transaction -> {
            String fromAddr = transaction.getFrom();
            String toAddr = transaction.getTo();

            String block_EthSub = transaction.getBlockNumber().toString();   //关键代码，更新区块高度，少了这个不行

            for (String addr:addrList){
                if (addr.equals(fromAddr)||addr.equals(toAddr)){          //如果两个地址都在库里，这里每次会重复存入两笔交易记录，共4笔insert … select … where not exist ……
                    String uuid = ethUtil.getUUID();
                    String hash = transaction.getHash();
                    String nonce=transaction.getNonce().toString();
                    String blockNumber = transaction.getBlockNumber().toString();
                    String transValue = Convert.fromWei(transaction.getValue().toString(), Convert.Unit.ETHER).toString();
                    transRecordDO.setId(uuid);
                    transRecordDO.setHash(hash);
                    transRecordDO.setNonce(nonce);
                    transRecordDO.setBlockNumber(blockNumber);
                    transRecordDO.setFromAddr(fromAddr);
                    transRecordDO.setToAddr(toAddr);
                    transRecordDO.setTransValue(transValue);
                    transRecordMapper.addTransRecord(transRecordDO);
                }
            }
        });
    }

//    异步，遍历库的address，然后更新余额信息
    @Override
    @Async
    public void updataBalance(List<String> addrList) {
    for (String addr:addrList){
        String myBalance = ethUtil.getMyBalance(web3j, addr).toString();
        accountMapper.updataBalance(addr,myBalance);
    }
    }
}
